<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button id="download" style="padding: 10px 20px;">下载</button>
  <script>
    async function downloadM3U8(m3u8Url) {
      try {
        // 获取m3u8文件内容
        const m3u8Response = await fetch(m3u8Url);
        const m3u8Text = await m3u8Response.text();

        // 解析m3u8文件获取所有.ts文件的URL
        const tsUrls = m3u8Text.match(/[^\s\r\n]+\.ts(\?[^\s\r\n]*)?/g)
          .map(tsPath => {
            // 如果是完整URL，直接返回
            if (tsPath.startsWith('http')) {
              return tsPath;
            }
            // 如果是相对路径，需要根据基础URL构建完整URL
            const baseUrl = m3u8Url.substring(0, m3u8Url.lastIndexOf('/') + 1);
            return baseUrl + tsPath;
          });

        // 并行下载所有的.ts文件
        const tsBlobs = await Promise.all(tsUrls.map(url =>
          fetch(url).then(res => res.blob())
        ));

        // 合并所有的.ts文件
        const chunks = [];
        for (const blob of tsBlobs) {
          const arrayBuffer = await blob.arrayBuffer();
          chunks.push(arrayBuffer);
        }

        // 创建合并后的Blob
        const videoBlob = new Blob(chunks, { type: 'video/MP2T' });

        // 创建下载链接
        const url = URL.createObjectURL(videoBlob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'm3u8_video.ts';
        document.body.appendChild(a);
        a.click();

        // 清理
        URL.revokeObjectURL(url);
        document.body.removeChild(a);

      } catch (err) {
        console.error('下载失败:', err);
      }
    }
  </script>
  <script>
    var videoUrl = 'https://m.media-amazon.com/images/S/vse-vms-transcoding-artifact-us-east-1-prod/bda11534-a8e7-4366-a39a-a88c48817c27/default.jobtemplate.hls360.m3u8';
    // var videoUrl = 'https://vod3.cf.dmcdn.net/sec2(eCZ4WpOWEF3hXMj7d9TbcMeJalFkKEOYr9rQdHBUJrEcZSkqhoAdgeQj2WDgXpD6kezmjO0Eymj1K35fAPqy3JlhwUVATjDgN6wwDVz_uh-9TMdz-KUlc9l-Wrzr7aPi9V3DvYrAmfCG_M1LHzmT8-bhE0xLbGOB8HJ-sCZ-BOB03natGFqdSTrVpadXXu6Q)/video/029/186/556681920_mp4_h264_aac_hq_1.m3u8';

    window.testXZ = async () => {
      //       const m3u8Text = `#EXTM3U
      // #EXT-X-VERSION:5
      // #EXT-X-PLAYLIST-TYPE:VOD
      // #EXT-X-TARGETDURATION:3
      // #EXTINF:3.003000,
      // ../../../frag(1)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(2)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(3)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(4)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(5)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(6)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(7)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(8)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(9)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(10)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(11)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(12)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(13)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(14)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(15)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(16)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(17)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(18)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(19)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(20)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(21)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(22)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(23)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(24)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(25)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(26)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(27)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(28)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(29)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003010,
      // ../../../frag(30)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(31)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(32)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:3.003000,
      // ../../../frag(33)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXTINF:1.968640,
      // ../../../frag(34)/video/029/186/556681920_mp4_h264_aac_hq_1.ts
      // #EXT-X-ENDLIST
      // `;
      const m3u8Text = `#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:6,
default.jobtemplate.hls360_00001.ts
#EXTINF:6,
default.jobtemplate.hls360_00002.ts
#EXTINF:6,
default.jobtemplate.hls360_00003.ts
#EXTINF:6,
default.jobtemplate.hls360_00004.ts
#EXTINF:6,
default.jobtemplate.hls360_00005.ts
#EXTINF:4,
default.jobtemplate.hls360_00006.ts
#EXT-X-ENDLIST
`;

      // 解析m3u8文件获取所有.ts文件的URL
      const tsUrls = m3u8Text.match(/[^\s\r\n]+\.ts(\?[^\s\r\n]*)?/g)
        .map(tsPath => {
          // 如果是完整URL，直接返回
          if (tsPath.startsWith('http')) {
            return tsPath;
          }
          // 如果是相对路径，需要根据基础URL构建完整URL
          const baseUrl = videoUrl.substring(0, videoUrl.lastIndexOf('/') + 1);
          console.log(tsPath);
          return baseUrl + tsPath;
        });
      // console.log(tsUrls);
      // 并行下载所有的.ts文件
      const tsBlobs = await Promise.all(tsUrls.map(url =>
        fetch(url).then(res => res.blob())
      ));

      // 合并所有的.ts文件
      const chunks = [];
      for (const blob of tsBlobs) {
        const arrayBuffer = await blob.arrayBuffer();
        chunks.push(arrayBuffer);
      }

      // 创建合并后的Blob
      const videoBlob = new Blob(chunks, { type: 'video/MP2T' });

      // 创建下载链接
      const url = URL.createObjectURL(videoBlob);

      console.log(url);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'm3u8_video.ts';
      document.body.appendChild(a);
      a.click();
    };

    // download.addEventListener('click', () => {
    //   downloadM3U8(videoUrl);
    // });
  </script>
</body>

</html>